/** 
 * Copyright (C) 2018 Jeebiz (http://jeebiz.net).
 * All Rights Reserved. 
 */
package net.jeebiz.cloud.authz.facex.web.mvc;

import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.boot.biz.userdetails.SecurityPrincipal;
import org.springframework.security.boot.utils.SubjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.jeebiz.cloud.api.ApiCode;
import net.jeebiz.cloud.api.ApiRestResponse;
import net.jeebiz.cloud.api.annotation.BusinessLog;
import net.jeebiz.cloud.api.annotation.BusinessType;
import net.jeebiz.cloud.api.webmvc.BaseApiController;
import net.jeebiz.cloud.api.webmvc.Result;
import net.jeebiz.cloud.authz.facex.dao.entities.AuthzFaceModel;
import net.jeebiz.cloud.authz.facex.service.IAuthzFaceService;
import net.jeebiz.cloud.authz.facex.setup.Constants;
import net.jeebiz.cloud.authz.facex.web.vo.AuthzFacePaginationVo;
import net.jeebiz.cloud.authz.facex.web.vo.AuthzFaceVo;

@Api(tags = "人脸识别：服务接口")
@RestController
@RequestMapping(value = "/authz/face/")
@Validated
public class AuthzFaceController extends BaseApiController {

	@Autowired
	protected IAuthzFaceService authzFaceService;
	
	@ApiOperation(value = "分页查询人脸识别数据信息", notes = "分页查询人脸识别数据信息")
	@ApiImplicitParams({
		@ApiImplicitParam(paramType = "body", name = "paginationVo", value = "分页查询参数", dataType = "AuthzFacePaginationVo") 
	})
	@BusinessLog(module = Constants.AUTHZ_FACE, business = Constants.Biz.AUTHZ_FACE_LIST, opt = BusinessType.SELECT)
	@PostMapping("list")
	@PreAuthorize("authenticated and (hasAuthority('face:list') or hasAuthority('*')) ")
	@ResponseBody
	public Object list(@Valid @RequestBody AuthzFacePaginationVo paginationVo) throws Exception {
		
		AuthzFaceModel model = getBeanMapper().map(paginationVo, AuthzFaceModel.class);
		Page<AuthzFaceModel> pageResult = getAuthzFaceService().getPagedList(model);
		List<AuthzFaceVo> retList = Lists.newArrayList();
		for (AuthzFaceModel orgModel : pageResult.getRecords()) {
			retList.add(getBeanMapper().map(orgModel, AuthzFaceVo.class));
		}
		
		return new Result<AuthzFaceVo>(pageResult, retList);
		
	}
	
	@ApiOperation(value = "人脸扫描", notes = "检测图片中的人脸并存储检查合格的人脸图片作为识别的底片")
	@BusinessLog(module = Constants.AUTHZ_FACE, business = Constants.Biz.AUTHZ_FACE_DETECT, opt = BusinessType.INSERT)
	@PostMapping("scanning")
	@PreAuthorize("authenticated")
	@ResponseBody
	public ApiRestResponse<JSONObject> scanning(@Valid
			@ApiParam(value = "人脸图片文件", required = true) @RequestParam(value = "image") 
			@NotNull(message = "人脸图片不能为空") MultipartFile image) throws Exception {
		SecurityPrincipal principal = SubjectUtils.getPrincipal(SecurityPrincipal.class);
		JSONObject detect = getAuthzFaceService().scanning(principal.getUserid(), image);
		if(detect == null || !StringUtils.equalsIgnoreCase(detect.getString("error_code"), "0")) {
			return ApiRestResponse.fail(detect);
		}
		return ApiRestResponse.success(detect);
	}
	
	@ApiOperation(value = "人脸检测与属性分析", notes = "检测图片中的人脸并标记出位置信息")
	@BusinessLog(module = Constants.AUTHZ_FACE, business = Constants.Biz.AUTHZ_FACE_DETECT, opt = BusinessType.INSERT)
	@PostMapping("detect")
	@PreAuthorize("authenticated")
	@ResponseBody
	public ApiRestResponse<JSONObject> detect(@Valid
			@ApiParam(value = "人脸图片文件", required = true) @RequestParam(value = "image") 
			@NotNull(message = "人脸图片不能为空") MultipartFile image) throws Exception {
		JSONObject detect = getAuthzFaceService().detect(image);
		if(detect == null || !StringUtils.equalsIgnoreCase(detect.getString("error_code"), "0")) {
			return ApiRestResponse.fail(detect);
		}
		return ApiRestResponse.success(detect);
	}
	
	@ApiOperation(value = "人脸对比", notes = "比对两张图片中人脸的相似度，并返回相似度分值（接口提供被对比图片上传字段，图片底片以历史采集记录为准）")
	@BusinessLog(module = Constants.AUTHZ_FACE, business = Constants.Biz.AUTHZ_FACE_MATCH, opt = BusinessType.INSERT)
	@PostMapping("match")
	@PreAuthorize("authenticated")
	@ResponseBody
	public ApiRestResponse<JSONObject> match(@Valid
			@ApiParam(value = "人脸图片文件", required = true) @RequestParam(value = "image") 
			@NotNull(message = "人脸图片不能为空") MultipartFile image) throws Exception {
		SecurityPrincipal principal = SubjectUtils.getPrincipal(SecurityPrincipal.class);
		JSONObject match = getAuthzFaceService().match(principal.getUserid(), image);
		if(match == null || !StringUtils.equalsIgnoreCase(match.getString("error_code"), "0")) {
			return ApiRestResponse.fail(match);
		}
		return ApiRestResponse.success(match);
	}
	
	@ApiOperation(value = "人脸搜索", notes = "在指定人脸集合中，找到最相似的人脸")
	@BusinessLog(module = Constants.AUTHZ_FACE, business = Constants.Biz.AUTHZ_FACE_SEARCH, opt = BusinessType.INSERT)
	@PostMapping("search")
	@PreAuthorize("authenticated")
	@ResponseBody
	public ApiRestResponse<JSONObject> search(@Valid
			@ApiParam(value = "人脸图片文件", required = true) @RequestParam(value = "image") 
			@NotNull(message = "人脸图片不能为空") MultipartFile image) throws Exception {
		JSONObject search = getAuthzFaceService().search(image);
		if(search == null || !StringUtils.equalsIgnoreCase(search.getString("error_code"), "0")) {
			return ApiRestResponse.fail(search);
		}
		return ApiRestResponse.success(search);
	}
	
	@ApiOperation(value = "人脸融合", notes = "对两张人脸进行融合处理，生成的人脸同时具备两张人脸的外貌特征（并不是换脸）")
	@BusinessLog(module = Constants.AUTHZ_FACE, business = Constants.Biz.AUTHZ_FACE_MERGE, opt = BusinessType.INSERT)
	@PostMapping("merge")
	@PreAuthorize("authenticated")
	@ResponseBody
	public ApiRestResponse<JSONObject> merge(@Valid
			@ApiParam(value = "模板图片文件", required = true) @RequestParam(value = "template") 
			@NotNull(message = "模板图片不能为空") MultipartFile template,
			@ApiParam(value = "人脸图片文件", required = true) @RequestParam(value = "target") 
			@NotNull(message = "人脸图片不能为空") MultipartFile target) throws Exception {
		JSONObject merge = getAuthzFaceService().merge(template, target);
		if(merge == null || !StringUtils.equalsIgnoreCase(merge.getString("error_code"), "0")) {
			return ApiRestResponse.fail(merge);
		}
		return ApiRestResponse.success(merge);
	}

	public IAuthzFaceService getAuthzFaceService() {
		return authzFaceService;
	}
	
}
